package api

import (
	"github.com/360EntSecGroup-Skylar/excelize"
	"github.com/gin-gonic/gin"
	"github.com/tealeg/xlsx"
	"go.uber.org/zap"
	"path/filepath"
	"seat-service/initialization"
	"seat-service/model/dto"
	"seat-service/response"
	service "seat-service/service/impl"
	"strconv"
	"time"
)

type ClassroomAdminApi struct {
}

var classAdminService service.ClassroomAdminService

func (c *ClassroomAdminApi) GetClassroomByConditions(context *gin.Context) {
	//接收请求参数
	var conditionClassroom dto.GetClassroomCondition
	if err := context.ShouldBindJSON(&conditionClassroom); err != nil {
		resp.Fail(context, response.CodeParamError, nil)
		return
	}
	//拿到结果
	count, classroomInformation, err := classAdminService.SelectClassroomByCondition(conditionClassroom)
	if err != nil {
		initialization.SeatLogger.Error("classAdminService.SelectClassroomByCondition(conditionClassroom) is failed", zap.Error(err))
		resp.Fail(context, response.CodeServerBusy, nil)
		return
	}
	respData := struct {
		Classrooms []dto.ClassroomInformations `json:"classrooms"`
		Total      int64                       `json:"total"`
	}{
		Classrooms: classroomInformation,
		Total:      count,
	}
	resp.Success(context, response.CodeSuccess, respData)
}

func (c *ClassroomAdminApi) GetClassroomById(context *gin.Context) {
	//接收请求参数
	classroomIdStr := context.Query("classroom_id")
	classroomId, err := strconv.Atoi(classroomIdStr)
	if err != nil {
		initialization.SeatLogger.Error("strconv.Atoi(classroomIdStr) is failed", zap.Error(err))
		resp.Fail(context, response.CodeParamError, nil)
		return
	}
	classInformation, err := classAdminService.SelectClassroomById(classroomId)
	if err != nil {
		initialization.SeatLogger.Error("classAdminService.SelectClassroomById(classroomId)", zap.Error(err))
		resp.Fail(context, response.CodeServerBusy, nil)
		return
	}
	resp.Success(context, response.CodeSuccess, classInformation)
}

func (c *ClassroomAdminApi) UpdateClassroomById(context *gin.Context) {
	//接收请求参数
	var newClassInformation dto.ClassroomInformations
	if err := context.ShouldBindJSON(&newClassInformation); err != nil {
		resp.Fail(context, response.CodeParamError, nil)
		return
	}
	updateAfterInformation, err := classAdminService.UpdateClassroomInformationById(newClassInformation)
	if err != nil {
		if err.Error() == "BuildNotExist" {
			resp.Fail(context, response.BuildNoExist, nil)
			return
		}
		initialization.SeatLogger.Error("classAdminService.UpdateClassroomInformationById(newClassInformation) is failed", zap.Error(err))
		resp.Fail(context, response.CodeServerBusy, nil)
		return
	}
	if updateAfterInformation.ClassroomStatus == 0 && newClassInformation.ClassroomStatus != updateAfterInformation.ClassroomStatus {
		parse, _ := time.Parse("2006-01-02 15:04:05", updateAfterInformation.LockEndTime)
		duration := time.Now().Sub(parse)
		if duration > 0 {
			time.AfterFunc(duration, func() {
				errT := classAdminService.TimerClassroom(updateAfterInformation)
				if errT != nil {
					initialization.SeatLogger.Error("计时器修改教室状态失败，教室id：" + strconv.Itoa(newClassInformation.ID))
				}
			})
		}
	}
	resp.Success(context, response.CodeSuccess, updateAfterInformation)
}

func (c *ClassroomAdminApi) AddClassroomData(context *gin.Context) {
	//接收请求参数
	var addData dto.AddClassroom
	if err := context.ShouldBindJSON(&addData); err != nil {
		resp.Fail(context, response.CodeParamError, nil)
		return
	}
	err := classAdminService.AddClassroom(addData)
	if err != nil {
		if err.Error() == "BuildNotExist" {
			resp.Fail(context, response.BuildNoExist, nil)
			return
		}
		initialization.SeatLogger.Error("classAdminService.AddClassroom(addData) is failed", zap.Error(err))
		resp.Fail(context, response.CodeServerBusy, nil)
		return
	}
	resp.Success(context, response.CodeSuccess, nil)
}

func (c *ClassroomAdminApi) DeleteClassroom(context *gin.Context) {
	var classroom dto.DeleteClassIds
	if err := context.ShouldBindJSON(&classroom); err != nil {
		resp.Fail(context, response.CodeParamError, nil)
		return
	}
	err := classAdminService.DeleteClassroom(classroom)
	if err != nil {
		initialization.SeatLogger.Error("classAdminService.DeleteClassroom(classroom) is failed", zap.Error(err))
		resp.Fail(context, response.CodeServerBusy, nil)
		return
	}
	resp.Success(context, response.CodeSuccess, nil)
}

// ExportClassroomExcel 导出教室模板
func (c *ClassroomAdminApi) ExportClassroomExcel(context *gin.Context) {
	file := xlsx.NewFile()
	//添加工作表
	sheet, err := file.AddSheet("Sheet1")
	if err != nil {
		initialization.SeatLogger.Error("file.AddSheet(\"Sheet1\") is failed", zap.Error(err))
		resp.Fail(context, response.GetFileFail, nil)
		return
	}
	//添加标题行
	titles := sheet.AddRow()
	titles.AddCell().SetValue("教室名称")
	titles.AddCell().SetValue("楼栋名称")
	titles.AddCell().SetValue("教室状态")
	titles.AddCell().SetValue("教室开始锁定时间")
	titles.AddCell().SetValue("教室结束锁定时间")
	titles.AddCell().SetValue("教室属性")
	titles.AddCell().SetValue("合教")
	titles.AddCell().SetValue("教室座位")
	//创建示例行
	row := sheet.AddRow()
	row.AddCell().SetValue("A102")
	row.AddCell().SetValue("零号楼")
	row.AddCell().SetValue("禁用:0 锁定:1")
	row.AddCell().SetValue("2023-11-20 13:00")
	row.AddCell().SetValue("2023-11-20 13:00")
	row.AddCell().SetValue("计算机教室")
	row.AddCell().SetValue("1")
	row.AddCell().SetValue("100")
	//设置Http响应头
	context.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
	context.Header("Content-Disposition", "attachment; filename=教室信息.xlsx")
	//将Excel文件返回给前端
	if err := file.Write(context.Writer); err != nil {
		initialization.SeatLogger.Error("xlsx.Write(context.Writer) is error", zap.Error(err))
		resp.Fail(context, response.GetFileFail, nil)
		return
	}
}

func (c *ClassroomAdminApi) MoreAddClassroom(context *gin.Context) {
	//批量导入数据
	classroomExcel, err := context.FormFile("classroom")
	if err != nil {
		initialization.SeatLogger.Error("context.FormFile(\"classroom\") is failed", zap.Error(err))
		resp.Fail(context, response.UploadFileFail, nil)
		return
	}
	//将上传的文件保存到 uploads/excel 下面
	fielPath := filepath.Join("uploads", "excel", classroomExcel.Filename)
	if err := context.SaveUploadedFile(classroomExcel, fielPath); err != nil {
		initialization.SeatLogger.Error("context.SaveUploadedFile(classroomExcel , fielPath) is failed", zap.Error(err))
		resp.Fail(context, response.UploadFileFail, nil)
		return
	}
	//解析Excel文件
	classXlsx, err := excelize.OpenFile(fielPath)
	if err != nil {
		initialization.SeatLogger.Error("excelize.OpenFile(fielPath) is failed", zap.Error(err))
		resp.Fail(context, response.UploadFileFail, nil)
		return
	}
	//获取excel中的具体列的值
	rows := classXlsx.GetRows("Sheet" + "1")
	//循环遍历
	var classrooms []dto.AddClassroom
	for _, row := range rows {
		var classroom dto.AddClassroom
		layout := "1/2/06 15:04"
		if row[3] != "" {
			//锁定开始时间
			parsedTime, _ := time.Parse(layout, row[3])
			layoutAsString := "2006-01-02 15:04"
			classroom.LockStartTime = parsedTime.Format(layoutAsString)
		}
		if row[4] != "" {
			//锁定结束时间
			parsedTime, _ := time.Parse(layout, row[4])
			layoutAsString := "2006-01-02 15:04"
			classroom.LockEndTime = parsedTime.Format(layoutAsString)
		}
		status, _ := strconv.Atoi(row[2])
		classroom.ClassroomStatus = status
		classroom.ClassroomProperty = row[5]
		classroom.Location = row[0]
		classroom.BuildName = row[1]
		classroom.IsLargeClassroom = row[6]
		classroom.Seating = row[7]
		classrooms = append(classrooms, classroom)
	}
	errClassrooms, err := classAdminService.InsertClassrooms(classrooms[1:])
	if err != nil {
		initialization.SeatLogger.Error("classAdminService.InsertClassrooms(classrooms) is failed", zap.Error(err))
		resp.Fail(context, response.ClassroomIsExist, errClassrooms)
		return
	}
	resp.Success(context, response.CodeSuccess, nil)
}
